﻿Imports System.ComponentModel, System.IO, System.Text, System.Threading

Namespace UI

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <remarks></remarks>
    <DockingAttribute(DockingBehavior.Ask)>
    Public Class FolderExplorer

        ''' <summary>
        ''' The Delegate for the OnAfterNodeSelect Event
        ''' </summary>
        ''' <param name="pathName">The Path of the Item Being Selected</param>
        ''' <param name="CSI">The Folder Model for the Selected Node</param>
        ''' <remarks></remarks>
        Public Delegate Sub OnAfterNodeSelect_Delegate(ByVal pathName As String, ByVal CSI As CShItem)
        ''' <summary>
        ''' Triggered After A Node is Clicked and Contains that Node's Info
        ''' </summary>
        ''' <remarks></remarks>
        Public Event OnAfterNodeSelect As OnAfterNodeSelect_Delegate

#Region "       PreMade         >>>"

        'avoid Globalization problem-- an empty timevalue
        Dim testTime As New DateTime(1, 1, 1, 0, 0, 0)

        Private LastSelectedCSI As CShItem
        Private Shared Event1 As New ManualResetEvent(True)





        Private Sub lv1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles lv1.DoubleClick
            Dim csi As CShItem = lv1.SelectedItems(0).Tag
            'csi.DebugDump()
            'csi.DumpPidl(csi.PIDL)
            If csi.IsFolder Then
                ExpTree1.ExpandANode(csi)
            Else
                Try
                    Process.Start(csi.Path)
                Catch ex As Exception
                    MsgBox(ex.Message, MsgBoxStyle.OkOnly, "Error in starting application")
                End Try
            End If
        End Sub


        Private Sub lv1_ItemDrag(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemDragEventArgs) Handles lv1.ItemDrag
            'Debug.WriteLine("Item Drag -- Item = " & e.Item.text)
            With lv1
                If .SelectedItems.Count > 0 Then
                    Dim toDrag As New ArrayList()
                    Dim lvItem As ListViewItem
                    Dim strD(.SelectedItems.Count - 1) As String
                    Dim i As Integer
                    For Each lvItem In .SelectedItems
                        toDrag.Add(lvItem.Tag)
                        strD(i) = CType(lvItem.Tag, CShItem).Path
                        i += 1
                    Next
                    'NOTE: FileDrop allowing auto conversion will generate
                    ' a Shell IDList Array on demand... but in some cases, the
                    ' resultant PIDLs can be different from what we want, so
                    ' do our own.
                    Dim Dobj As New DataObject()
                    Dim ms As MemoryStream
                    ms = CProcDataObject.MakeShellIDArray(toDrag)
                    With Dobj
                        If Not ms Is Nothing Then
                            .SetData("Shell IDList Array", True, ms)
                        End If
                        .SetData("FileDrop", True, strD)
                        .SetData(toDrag)
                    End With
                    Dim dEff As DragDropEffects
                    If e.Button = Windows.Forms.MouseButtons.Right Then
                        dEff = DragDropEffects.Copy Or DragDropEffects.Move Or DragDropEffects.Link
                    Else
                        dEff = DragDropEffects.Copy Or DragDropEffects.Move
                    End If
                    Dim res As DragDropEffects = .DoDragDrop(Dobj, dEff)
                    'Debug.WriteLine(res)
                    'Debug.WriteLine("")
                End If
            End With
        End Sub


        Private Sub AfterNodeSelect(ByVal pathName As String, ByVal CSI As CShItem) Handles ExpTree1.ExpTreeNodeSelected
            Dim dirList As New ArrayList()
            Dim fileList As New ArrayList()
            Dim TotalItems As Integer
            LastSelectedCSI = CSI
            If CSI.DisplayName.Equals(CShItem.strMyComputer) Then
                dirList = CSI.GetDirectories 'avoid re-query since only has dirs
            Else
                dirList = CSI.GetDirectories
                fileList = CSI.GetFiles
            End If
            Event1.WaitOne()
            TotalItems = dirList.Count + fileList.Count
            If TotalItems > 0 Then
                Dim item As CShItem
                dirList.Sort()
                fileList.Sort()
                Me.Text = pathName
                sbr1.Text = pathName & "                 " & _
                            dirList.Count & " Directories " & fileList.Count & " Files"
                Dim combList As New ArrayList(TotalItems)
                combList.AddRange(dirList)
                combList.AddRange(fileList)

                'Build the ListViewItems & add to lv1
                lv1.BeginUpdate()
                lv1.Items.Clear()
                lv1.Refresh()
                For Each item In combList
                    Dim lvi As New ListViewItem(item.DisplayName)
                    With lvi
                        If Not item.IsDisk And item.IsFileSystem Then
                            Dim attr As FileAttributes
                            attr = GetAttr(item.Path)
                            Dim SB As New StringBuilder()
                            If (attr And FileAttributes.System) = FileAttributes.System Then SB.Append("S")
                            If (attr And FileAttributes.Hidden) = FileAttributes.Hidden Then SB.Append("H")
                            If (attr And FileAttributes.ReadOnly) = FileAttributes.ReadOnly Then SB.Append("R")
                            If (attr And FileAttributes.Archive) = FileAttributes.Archive Then SB.Append("A")
                            .SubItems.Add(SB.ToString)
                        Else : .SubItems.Add("")
                        End If
                        If Not item.IsDisk And item.IsFileSystem And Not item.IsFolder Then
                            If item.Length > 1024 Then
                                .SubItems.Add(Format(item.Length / 1024, "#,### KB"))
                            Else
                                .SubItems.Add(Format(item.Length, "##0 Bytes"))
                            End If
                        Else
                            .SubItems.Add("")
                        End If
                        .SubItems.Add(item.TypeName)
                        If item.IsDisk Then
                            .SubItems.Add("")
                        Else
                            If item.LastWriteTime = testTime Then '"#1/1/0001 12:00:00 AM#" is empty
                                .SubItems.Add("")
                            Else
                                .SubItems.Add(item.LastWriteTime)
                            End If
                        End If
                        '.ImageIndex = SystemImageListManager.GetIconIndex(item, False)
                        .Tag = item
                    End With
                    lv1.Items.Add(lvi)
                Next
                lv1.EndUpdate()
                LoadLV1Images()
            Else
                lv1.Items.Clear()
                sbr1.Text = pathName & " Has No Items"
            End If
            RaiseEvent OnAfterNodeSelect(pathName, CSI)
        End Sub


#Region "   IconIndex Loading Thread"
        Private Sub LoadLV1Images()
            Dim ts As New ThreadStart(AddressOf DoLoadLv)
            Dim ot As New Thread(ts)

            ot.SetApartmentState(ApartmentState.STA)

            Event1.Reset()
            ot.Start()
        End Sub

        <DebuggerNonUserCode()>
        Private Sub DoLoadLv()
            Dim lvi As ListViewItem
            On Error Resume Next
            For Each lvi In lv1.Items
                lvi.ImageIndex = SystemImageListManager.GetIconIndex(lvi.Tag, False)
            Next
            Event1.Set()
        End Sub
#End Region


#End Region



#Region "       Aaron           >>>"
        <Category("Options"), Description("URL of Root Folder. If Empty the Default Root Folder is used"), Browsable(True)> _
        Public Property StartingRootFolder As String = "C:\"
        Public SelectedFolder As CShItem



#Region "       Set View                >>>"

        Private Sub LargeIconToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LargeIconToolStripMenuItem.Click
            lv1.View = View.LargeIcon
        End Sub

        Private Sub SmallIconToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SmallIconToolStripMenuItem.Click
            lv1.View = View.SmallIcon
        End Sub

        Private Sub ListToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListToolStripMenuItem.Click
            lv1.View = View.List
        End Sub

        Private Sub DetailToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DetailToolStripMenuItem.Click
            lv1.View = View.Details
        End Sub

#End Region


#Region "       Misc                    >>>"




        Public Sub ChangeRootFolder(ByVal NewRootFolder As String)
            If NewRootFolder = "" Then NewRootFolder = "C\"
            Dim cDir As CShItem = FS.CShItem.GetCShItem(NewRootFolder)
            If cDir Is Nothing Then Exit Sub
            If cDir.IsFolder Then ExpTree1.RootItem = cDir
        End Sub


        Private Sub btnGoTo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGoTo.Click
            Select Case txtFolder.Text
                Case "Home"
                    ChangeRootFolder(StartingRootFolder)
                Case "Desktop"
                    ChangeRootFolder(My.Computer.FileSystem.SpecialDirectories.Desktop)
                Case "Folder Selector"
                    Dim B As New FolderBrowserDialog With {.SelectedPath = "C:\Aaron", .Description = "Select the New Base Folder"}
                    B.ShowDialog() : ChangeRootFolder(B.SelectedPath)
                Case Else
                    ChangeRootFolder(txtFolder.Text)
            End Select
        End Sub


        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            'In this case, the below is perfectly safe. It is not recommended as
            ' a general solution. Feel free to modify this demo to properly do
            ' cross thread modification of the ListView.
            Control.CheckForIllegalCrossThreadCalls = False

            'If Not StartingRootFolder = "" Then ChangeRootFolder(StartingRootFolder) '<--I did that I think



            'I Added This Here it Get the Icons to Show up...They do not Show up the First Time, but show every time after
            SystemImageListManager.SetListViewImageList(lv1, True, False)
            SystemImageListManager.SetListViewImageList(lv1, False, False)

            'This Corrects the Above Problem by Reloading the First Page

            If StartingRootFolder = "" Then
                ExpTree1.RootItem = ExpTree1.RootItem
            Else
                ChangeRootFolder(StartingRootFolder)
            End If



        End Sub


        Private Sub HelpToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles HelpToolStripMenuItem.Click
            Const C As String = vbCrLf & vbCrLf
            Dim S As String = "Here is a List of Tips and Tricks" & C & vbCrLf & "1.  RightClick the {Folder Panel} For Advanced Actions" & C
            S += "2.  Click the Down Arrow on the ComboBox Next to the [Go To Folder Button] For Special Folder Selecting Actions" & C
            S += "3.  You can Use the [Set View] Menu to Select Folder Viewing Options"
            MsgBox(S)
        End Sub


        Private Sub lv1_ItemSelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ListViewItemSelectionChangedEventArgs) Handles lv1.ItemSelectionChanged
            If lv1.SelectedItems.Count = 0 Then Exit Sub
            Dim csi As CShItem = lv1.SelectedItems(0).Tag
            SelectedFolder = csi
            Debug.WriteLine(vbCrLf & "Display Name: " & csi.DisplayName & vbCrLf & "Path: " & csi.Path)
        End Sub


#End Region


#Region "       ContextMenu Files       >>>"

        Private Sub DeleteToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DeleteToolStripMenuItem.Click
            FileFolder.[New](SelectedFolder.Path).Actions.SendToRecycleBinA()
            'Aaron.Main.FS.File_Folder.Delete_WithMSG(SelectedFolder.Path)
            AfterNodeSelect(ExpTree1.SelectedItem.Path, ExpTree1.SelectedItem)
            ExpTree1.RefreshTree(ExpTree1.RootItem)
        End Sub


        Private Sub RenameToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RenameToolStripMenuItem.Click
            Dim NewName As String = InputBox("Enter Name") : If String.IsNullOrWhiteSpace(NewName) Then Exit Sub
            Dim FileExtension As String = lv1.SelectedItems(0).Text.Split(".").Last
            Dim Path As String = ExpTree1.SelectedItem.Path & "\"

            If FS.FileFolder.IsPathValid(NewName, True) = False Then
                Exit Sub
            ElseIf New FS.FileFolder(Path & NewName & "." & FileExtension).Exists OrElse New FS.FileFolder(Path & NewName).Exists Then
                'Date 10/6/2011     Added OrElse New FS.FileFolder(T & S).Exists
                MsgBox("Name Already Used In Folder")
            Else
                'Date 10/6/2011     Refactored Below Code
                If lv1.SelectedItems(0).Text.Contains(".") Then
                    My.Computer.FileSystem.RenameFile(Path & lv1.SelectedItems(0).Text, NewName & "." & FileExtension)
                Else
                    My.Computer.FileSystem.RenameDirectory(NewName & FileExtension, Path)
                End If
                ExpTree1.RefreshTree()
                AfterNodeSelect(ExpTree1.SelectedItem.Path, ExpTree1.SelectedItem)

                'If New FS.FileFolder(T & S).Exists Then
                '    MsgBox("Name Already Used")
                'Else
                '    My.Computer.FileSystem.RenameDirectory(T & N, S)
                'End If
            End If
        End Sub

        Private Sub FileCreator(ByVal FileType As FSObject.FSType)
            Dim S As String = InputBox("Enter Name") : If String.IsNullOrWhiteSpace(S) Then Exit Sub
            FS.FSObject.GetObject(FileType).CreateMethod.Invoke(S)
            AfterNodeSelect(ExpTree1.SelectedItem.Path, ExpTree1.SelectedItem)
        End Sub



        'TODO Replace with AddEvent In the Forms LoadEvent Soon
        Private Sub WordToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles WordToolStripMenuItem.Click
            FileCreator(FSObject.FSType.Word)

            'Dim S As String = InputBox("Enter Name") : If S = "" Then Exit Sub
            '' If Aaron.Main.FS.Both.IsValid_Path(S) = False Then Exit Sub
            'Aaron.Main.FS.CreateSpecialFile(Aaron.Main.FS.File_Folder.SpecialFile.Word, ExpTree1.SelectedItem.Path & "\" & S)
            'AfterNodeSelect(ExpTree1.SelectedItem.Path, ExpTree1.SelectedItem)
        End Sub


        Private Sub ExcelToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExcelToolStripMenuItem.Click
            FileCreator(FSObject.FSType.Excel)
            'Dim S As String = InputBox("Enter Name") : If S = "" Then Exit Sub
            ''   If Aaron.Main.FS.Both.IsValid_Path(S) = False Then Exit Sub
            'Aaron.Main.FS.CreateSpecialFile(Aaron.Main.FS.File_Folder.SpecialFile.Excel, ExpTree1.SelectedItem.Path & "\" & S)
            'AfterNodeSelect(ExpTree1.SelectedItem.Path, ExpTree1.SelectedItem)
        End Sub


        Private Sub PowerPointToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PowerPointToolStripMenuItem.Click
            FileCreator(FSObject.FSType.Word)

            'Dim S As String = InputBox("Enter Name") : If S = "" Then Exit Sub
            ''  If Aaron.Main.FS.Both.IsValid_Path(S) = False Then Exit Sub
            'Aaron.Main.FS.CreateSpecialFile(Aaron.Main.FS.File_Folder.SpecialFile.PowerPoint, ExpTree1.SelectedItem.Path & "\" & S)
            'AfterNodeSelect(ExpTree1.SelectedItem.Path, ExpTree1.SelectedItem)
        End Sub


        Private Sub tsiCreateFolder_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsiCreateFolder.Click
            Dim S As String = InputBox("Enter Name") : If S = "" Then Exit Sub
            Dim T As String = ExpTree1.SelectedItem.Path & "\"


            '  If Aaron.Main.FS.Both.IsValid_Path(S) = False Then Exit Sub

            ' If Aaron.Main.FS.Both.Exists(T & S) Then
            'MsgBox("Name Already Used In Folder")
            'Else
            Main.FS.Create_FolderFile(Main.FS.Create_FolderFile_Action.Folder_NoPrompt, T & S)
            ExpTree1.RefreshTree(ExpTree1.RootItem)
            'End If
        End Sub


#End Region


#Region "       ContextMenu Folders     >>>"

        Private Sub tsiOpenFolder_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsiOpenFolder.Click, tsiGoDown.Click, tsiChangeBase.Click
            Try : Dim T As String = sender.name
                Dim cDir As CShItem = FS.CShItem.GetCShItem(ExpTree1.SelectedItem.Path)
                Select Case T
                    Case tsiOpenFolder.Name
                        If cDir.IsFolder Then Process.Start(cDir.Path)
                    Case tsiChangeBase.Name
                        ChangeRootFolder(cDir.Path)
                    Case tsiGoDown.Name
                        ChangeRootFolder(cDir.Parent.Path)
                End Select : Catch : End Try
        End Sub

        Private Sub tsiChangeName_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tsiChangeName.Click
            Dim S As String = InputBox("Enter Name") : If S = "" Then Exit Sub

            Dim T As String = ExpTree1.SelectedItem.Path
            Dim T1 As String = ExpTree1.SelectedItem.Path.Split("\").Last
            Dim T2 As String = (ExpTree1.SelectedItem.Path.Remove(T.Length - T1.Length, T1.Length))
            Dim T3 As String = T2 & S


            For Each Item As String In S
                If Char.IsLetterOrDigit(Item) Or Char.IsWhiteSpace(Item) Then
                Else
                    MsgBox("File Names may Only Contain Numbers or Letters")
                    Exit Sub
                End If
            Next

            If New FS.FileFolder(T3).Exists Then
                MsgBox("Name Already Used")
            Else
                My.Computer.FileSystem.RenameDirectory(ExpTree1.SelectedItem.Path, S)
                ExpTree1.RefreshTree(ExpTree1.RootItem)
            End If
        End Sub

#End Region









#End Region


    End Class

End Namespace